#include "server.h"

Tcpserver::Tcpserver(int num):next_thread(0)
{
    if(num<=0)
    {
        qDebug()<<" num <0\n";
    }
    threadnum=num;
    thread_pool=new Thread[threadnum];
    if(thread_pool==NULL)
     {
        qDebug()<<"pool create fail\n";
    }
    m_base=event_base_new();
}

int Tcpserver::listen(int port, const char *ip)
{
     sockaddr_in sin;
     memset(&sin,0,sizeof(sin));
     sin.sin_family=AF_INET;
     sin.sin_port=htons(port);
     if(ip!=NULL)
     {
      inet_aton(ip,&sin.sin_addr);
     }

     listener=evconnlistener_new_bind(m_base,listen_cb,
                                      this,
                                      LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
                                      -1,
                                      (sockaddr*)&sin,
                                      sizeof (sin));
     if(!listener)
     {
         qDebug()<<" listner error\n";
         return -1;
     }
     for(int i=0;i<threadnum;i++)
     {
         thread_pool[i].start();
         qDebug()<<"线程 "<<i<<"启动\n";
     }
     return 0;
}

void Tcpserver::start()
{
    qDebug()<<"sever run\n";
    event_base_dispatch(m_base);
    evconnlistener_free(listener);
    event_base_free(m_base);
}

void Tcpserver::listen_cb(evconnlistener *listener, int fd, sockaddr *addr, int socklen, void *ptr)
{
    qDebug()<<" 有链接\n";
    Tcpserver*p=(Tcpserver*)ptr;

    p->listen_run(fd,(sockaddr_in*)addr);

}

void Tcpserver::listen_run(int fd, sockaddr_in *sin)
{
    char*ip=inet_ntoa(sin->sin_addr);
    uint16_t prot=ntohs(sin->sin_port);


    event_base*base=thread_pool[(next_thread)%threadnum].getbase();
    next_thread++;
    bufferevent* bufferev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    if(!bufferev)
    {
        qDebug()<<" bufferev creat fail\n";
        return;
    }
    Tcpsocket*s=new Tcpsocket(bufferev,this,ip,prot);
    bufferevent_setcb(bufferev,s->Readeventcb,s->Writeevnetcb,s->Closeeventcb,s);
    bufferevent_enable(bufferev,EV_READ);
    bufferevent_enable(bufferev,EV_WRITE);
    bufferevent_enable(bufferev,EV_SIGNAL);
    //调用客户端链接事件
    connectEvent(s);

}
















